﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UtilZ.Dotnet.Ex.ZLog;

namespace UtilZ.Dotnet.Ex.Communication.Net.Ftp
{
    /// <summary>
    /// 认证密码
    /// Authentication password.
    /// </summary>
    internal class FtpPASSCommand : FtpCommandAbs
    {
        /***********************************************************************************************************
        * [PASS]（Password，密码）命令
        * 说明：向远程系统发送用户的密码，该命令在USER命令后使用。
        * 
        * 用法：PASS<Password><CRLF>
        * 参数：Password是由USER命令指定的已注册用户密码。
        * 例子：
        * SendData "PASS mypassworD" + “/r/n
        * 
        * 注释：在连接到一台FTP服务器的端口21并接收到一个由代码220打头的行，表示服务器已准备好你向它发USER和PASS命令，以登录进此FTP服务器之后，紧跟着发送USER命令。
        * PASS命令应该紧跟着USER命令。
        * 如果你在此FTP服务器上有帐号，就可以指定自己的用户名和密码。如果想匿名登录，可以指定用户名为“Anonymous”，而用自己的电子邮件地址当密码。
        * 返回值如下（粗体表示成功）：
        * 202  命令还没有被实现，在此站点上是多余的。
        * 230  用户已登录，请继续。
        * 332  登录需要帐号（请参看ACCT命令）。
        * 421  服务不可用，关闭控制连接。
        * 
        * 如果某项服务获知自己即将关闭，会向所有命令做出这个应答。
        * 500  语法错误，无法识别命令。这其中包括命令行过长之类的错误。
        * 501  参数或变元中有语法错误。
        * 530  无法登录。
        * 
        ************************************************************************************************************/


        public FtpPASSCommand()
            : base()
        {

        }

        protected override string[] GetNames()
        {
            return new string[] { FtpCommands.PASS };
        }

        protected override IFtpResponse PrimitiveExcute(FtpSession session, string command, string commandLine)
        {
            //Request: PASS IEUser@
            //Response: 230 User logged in.

            try
            {
                if (!string.Equals(session.LastCommand, FtpCommands.USER) &&
                    !string.Equals(session.LastCommand, FtpCommands.ACCT))
                {
                    return new FtpCodeResponse(FtpStatusCodes.Code503);
                }

                IFtpResponse response;
                switch (session.SessionStatus)
                {
                    case FtpSessionStatus.Success:
                        //用户已经登录
                        response = new FtpCodeResponse(FtpStatusCodes.Code230);
                        break;
                    case FtpSessionStatus.NoAuth:
                        response = new FtpCodeResponse(FtpStatusCodes.Code332);
                        break;
                    case FtpSessionStatus.AnonymousAccountValid:
                        //匿名账号登录不验证密码
                        session.SessionStatus = FtpSessionStatus.Success;
                        session.InitFtpPathManager();
                        response = new FtpCodeResponse(FtpStatusCodes.Code230);
                        break;
                    case FtpSessionStatus.AccountValid:
                        if (string.Equals(session.FtpUser.Password, commandLine))
                        {
                            session.SessionStatus = FtpSessionStatus.Success;
                            session.InitFtpPathManager();
                            response = new FtpCodeResponse(FtpStatusCodes.Code230);
                        }
                        else
                        {
                            response = new FtpCodeResponse(FtpStatusCodes.Code530, "password error.");
                        }
                        break;
                    default:
                        response = new FtpCodeResponse(FtpStatusCodes.Code421);
                        ZLoger.Warn($"ftp服务器命令\"{this.GetType().FullName}\"未实现的状态\"{session.SessionStatus.ToString()}\"");
                        break;
                }

                return response;
            }
            catch (Exception ex)
            {
                return new FtpCodeResponse(FtpStatusCodes.Code451, ex.Message);
            }
        }
    }

}
